package com.java.ReflectionDemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, InvocationTargetException, InstantiationException,
            IllegalAccessException, NoSuchFieldException {

        //获取类字节码文件对象的三种方式
        //1.Class.forName("类的全类名“)
        Class clazz1 = Class.forName("com.java.ReflectionDemo.Student");


        //2.通过class.属性获取
        Class clazz2 = Student.class;
        Class clazz3 = Student.class;

        ////因为class文件在硬盘中是唯一的，
        // 所以，当这个文件加载到内存之后产生的对象也是唯一的
        System.out.println(clazz2 == clazz1);

        //3.通过student对象获取字节码文件对象
        Student stu  = new Student("柳岩",20,"北京");
        Class clazz4 = stu.getClass();
        System.out.println(clazz2 == clazz4);

        //获取构造方法

        //1.获取所有仅被public修饰的构造方法
//        Constructor[] constructors = clazz1.getConstructors();
//        for (Constructor constructor : constructors) {
//            System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());
//        }

        //2.获取所有的构造方法
//        Constructor[] declaredConstructors = clazz1.getDeclaredConstructors();
//        for (Constructor declaredConstructor : declaredConstructors) {
//            System.out.println(declaredConstructor.getName()
//                    + "-->" + declaredConstructor.getParameterCount());
//        }

        //获取指定的构造方法,只能被public修饰
        //获取指定的带参构造
//        Constructor c1 = clazz1.getConstructor(String.class, int.class, String.class);
//        System.out.println(c1.getName() + "-->" + c1.getParameterCount());

        //获取指定的构造(所有构造都可以获取到，包括public包括private)
        Constructor c2 = clazz1.getDeclaredConstructor();
        System.out.println(c2.getName() + "-->" + c2.getParameterCount());

        //获取构造方法并创建对象
        Constructor c3 = clazz2.getDeclaredConstructor(String.class, int.class);
        //绕过权限访问控制检查
        c3.setAccessible(true);
        Student obj = (Student)c3.newInstance("张三", 20);

        System.out.println(obj);

        //获取成员变量
        Field[] declaredFields = clazz1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName() + " : " + declaredField.getType());
        }

        //获取name成员变量并修改获取值
        Field filed = clazz1.getDeclaredField("name");
        Student s = new Student("lisi", 18,"shanghai");
        filed.set(s,"王五");//修改值
        
        //获取值
        String res = (String)filed.get(s); //获取s对象name的值
        System.out.println(res);

        //获取指定的私有成员方法
        Method method = clazz2.getDeclaredMethod("func",int.class);
        System.out.println(method);

        Student s2 = new Student("小明",25,"chongqin");
        //获取成员方法并执行
        String res2 = (String) clazz3.getDeclaredMethod("func2", String.class).
                invoke(s2, "lsu");
        System.out.println(res2);
    }
}
